/*
 * Copyright 2007 Rob Nielsen
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * 	http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.googlecode.proxymatic.ioc.guice.autoboundary;

import com.google.inject.Binder;
import com.google.inject.Key;
import com.google.inject.Provider;
import static com.google.inject.Scopes.SINGLETON;
import com.googlecode.proxymatic.apps.autoboundary.AutoboundaryHelper;

import java.lang.annotation.Annotation;

public class AutoboundaryIntegration {
    public static void bindAutoboundaryHelper(Binder binder) {
        binder.bind(AutoboundaryHelper.class)
                .toProvider(AutoboundaryHelperProvider.class).in(SINGLETON);
    }

    public static <T> void bindAutoboundaryWrapperClasses(Binder binder, Class<T>... autoboundaryClasses) {
        for (int i = 0; i < autoboundaryClasses.length; i++) {
            bindAutoboundaryWrapperClass(binder, autoboundaryClasses[i]);
        }
    }

    public static <T> void bindAutoboundaryWrapperClass(Binder binder, Class<T> autoboundaryClass) {
        binder.bind(autoboundaryClass).toProvider(fromAutoboundaryWrapper(autoboundaryClass));
    }

    public static <T> void bindAutoboundaryWrapperClass(Binder binder, Class<T> autoboundaryClass, Class<? extends Annotation> annotationClass) {
        binder.bind(autoboundaryClass).annotatedWith(annotationClass).toProvider(fromAutoboundaryWrapper(autoboundaryClass, annotationClass));
    }

    public static <T> void bindAutoboundaryWrapperClass(Binder binder, Class<T> autoboundaryClass, Annotation annotation) {
        binder.bind(autoboundaryClass).annotatedWith(annotation).toProvider(fromAutoboundaryWrapper(autoboundaryClass, annotation));
    }

    public static <T> void bindAutoboundaryClasses(Binder binder, Class<T>... autoboundaryClasses) {
        for (int i = 0; i < autoboundaryClasses.length; i++) {
            bindAutoboundaryClass(binder, autoboundaryClasses[i]);
        }
    }

    public static <T> void bindAutoboundaryClass(Binder binder, Class<T> autoboundaryClass) {
        binder.bind(autoboundaryClass).toProvider(fromAutoboundary(autoboundaryClass));
    }

    public static <T> Provider<T> fromAutoboundaryWrapper(Class<T> autoboundaryClass) {
        return new AutoboundaryWrapperProvider<T>(Key.get(autoboundaryClass));
    }

    public static <T> Provider<T> fromAutoboundaryWrapper(Class<T> autoboundaryClass, Annotation annotation) {
        return new AutoboundaryWrapperProvider<T>(Key.get(autoboundaryClass, annotation));
    }

    public static <T> Provider<T> fromAutoboundaryWrapper(Class<T> autoboundaryClass, Class<? extends Annotation> annotationClass) {
        return new AutoboundaryWrapperProvider<T>(Key.get(autoboundaryClass, annotationClass));
    }

    public static <T> Provider<T> fromAutoboundary(Class<T> autoboundaryClass) {
        return new AutoboundaryProvider<T>(autoboundaryClass);
    }
}
